﻿using System;
using System.Collections.Generic;
using UnityEngine;

public class TimerMgr : IZUpdate
{
    private uint nextId = uint.MinValue + 1;
    //public List<uint> reIdList = new List<uint>();
    private List<TimerVO> timerRender = new List<TimerVO>();
    public List<TimeroutBaseVO> timerOutRender = new List<TimeroutBaseVO>();
    public Dictionary<uint, TimeroutBaseVO> timerOutDic = new Dictionary<uint, TimeroutBaseVO>();
    public Dictionary<string, float> timeLimitDic = new Dictionary<string, float>();

    public TimerMgr()
    {
        ClearAllTime();
    }

    public void ClearAllTime()
    {
        nextId = uint.MinValue + 1;
        //reIdList.Clear();
        timerRender.Clear();
        timerOutRender.Clear();
        timerOutDic.Clear();
        timeLimitDic.Clear();
    }

    public void AddFun(TimerVO vo)
    {
        if (!timerRender.Contains(vo))
        {
            vo.Init();
            timerRender.Add(vo);
        }
    }

    public void DelFun(TimerVO vo)
    {
        if (timerRender.Contains(vo))
        {
            timerRender.Remove(vo);
        }
    }

    public void ZUpdate()
    {
        for (int i = timerRender.Count - 1; i >= 0; i--)
        {
            if (timerRender.Count > i)
            {
                timerRender[i].Update();
            }
        }

        for (int i = timerOutRender.Count - 1; i >= 0; i--)
        {
            if (timerOutRender.Count > i)
            {
                timerOutRender[i].Update();
            }
        }
    }

    /// <summary>
    /// 判断是否满足连续操作条件，内部会重置时间
    /// </summary>
    /// <param name="key"></param>
    /// <param name="difTime"></param>
    /// <param name="isTip"></param>
    public bool IsCanOperate(string key, float difTime, bool isTip = false)
    {
        if (!timeLimitDic.ContainsKey(key))
        {
            timeLimitDic.Add(key, Time.time);
        }

        float last = timeLimitDic[key];
        if (Time.time - last <= difTime)
        {
            if (isTip)
            {
                //操作频繁，请稍后再试
            }
            return false;
        }
        return true;
    }

    /// <summary>
    /// 可选参数延时回调
    /// </summary>
    /// <typeparam name="Arg">参数类型，每个参数类型不一样且参数超过两个时 填object</typeparam>
    /// <param name="delayFun">回调函数</param>
    /// <param name="time">延时时间</param>
    /// <param name="args">可选参数</param>
    /// <returns>返回唯一延时id 可用于清除回调</returns>
    public uint SetTimeOut<Arg>(TimeoutArgFun<Arg> delayFun, float time, params Arg[] args)
    {
        TimeroutArgsVO<Arg> outVO = new TimeroutArgsVO<Arg>(delayFun, time, args);
        outVO.objID = GetObjID();
        timerOutRender.Add(outVO);
        timerOutDic.Add(outVO.objID, outVO);
        return outVO.objID;
    }

    /// <summary>
    /// 无参数延时回调
    /// </summary>
    /// <param name="delayFun">回调函数</param>
    /// <param name="time">延时时间，单位秒</param>
    /// <returns>返回唯一延时id 可用于清除回调</returns>
    public uint SetTimeOut(Action delayFun, float time)
    {
        Timerout0VO outVO = new Timerout0VO(delayFun,time);
        outVO.objID = GetObjID();
        timerOutRender.Add(outVO);
        timerOutDic.Add(outVO.objID, outVO);
        return outVO.objID;
    }
    
    /// <summary>
    /// 带一个参数延时回调
    /// </summary>
    /// <typeparam name="Arg">回调函数的唯一参数类型</typeparam>
    /// <param name="delayFun">回调函数</param>
    /// <param name="time">延时时间，单位秒</param>
    /// <param name="arg">回调方法要传入的参数</param>
    /// <returns>返回唯一延时id 可用于清除回调</returns>
    public uint SetTimeOut<Arg>(Action<Arg> delayFun, float time, Arg arg)
    {
        Timerout1VO<Arg> outVO = new Timerout1VO<Arg>(delayFun, time, arg);
        outVO.objID = GetObjID();
        timerOutRender.Add(outVO);
        timerOutDic.Add(outVO.objID, outVO);
        return outVO.objID;
    }

    /// <summary>
    /// 带两个参数延时回调
    /// </summary>
    /// <typeparam name="Arg1">回调函数的参数1类型</typeparam>
    /// <typeparam name="Arg2">回调函数的参数2类型</typeparam>
    /// <param name="delayFun">回调函数</param>
    /// <param name="time">延时时间，单位秒</param>
    /// <param name="arg1">回调方法要传入的参数1</param>
    /// <param name="arg2">回调方法要传入的参数2</param>
    /// <returns>返回唯一延时id 可用于清除回调</returns>
    public uint SetTimeOut<Arg1, Arg2>(Action<Arg1, Arg2> delayFun, float time, Arg1 arg1,Arg2 arg2)
    {
        Timerout2VO<Arg1, Arg2> outVO = new Timerout2VO<Arg1, Arg2>(delayFun, time, arg1,arg2);
        outVO.objID = GetObjID();
        timerOutRender.Add(outVO);
        timerOutDic.Add(outVO.objID, outVO);
        return outVO.objID;
    }

    public void ClearTimeOut(uint id)
    {
        if (timerOutDic.ContainsKey(id))
        {
            timerOutDic[id].Destroy();
            timerOutRender.Remove(timerOutDic[id]);
            timerOutDic.Remove(id);
            //reIdList.Add(id);
        }
    }

    public void ClearAllTimeOut()
    {
        for (int i = timerOutRender.Count - 1; i >= 0; i--)
        {
            if (timerOutRender.Count > i)
            {
                timerOutRender[i].Destroy();
                timerOutRender.RemoveAt(i);
            }
        }
        timerOutDic.Clear();
    }

    private uint GetObjID()
    {
        /*if (reIdList.Count > 0)
        {
            uint objID = reIdList[0];
            reIdList.RemoveAt(0);
            return objID;
        }*/
        return nextId++;
    }
}